package com.company.cloud.mall.modules.app.service.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;

import com.company.cloud.art.modules.api.response.Artist;
import com.company.cloud.art.modules.api.service.ArtArtistRemoteService;
import com.company.cloud.product.modules.api.response.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.company.cloud.acct.modules.api.constant.AcctOpTypeEnum;
import com.company.cloud.acct.modules.api.constant.AcctTypeEnum;
import com.company.cloud.acct.modules.api.request.AcctOpRequest;
import com.company.cloud.acct.modules.api.service.AccountRemoteService;
import com.company.cloud.common.bean.BaseClientResult;
import com.company.cloud.common.bean.LoginSimpleUserInfo;
import com.company.cloud.common.constant.BaseConstant.YNEnum;
import com.company.cloud.common.constant.BaseReturnEnum;
import com.company.cloud.common.exception.BusinessException;
import com.company.cloud.common.utils.CheckUtils;
import com.company.cloud.company.modules.api.response.CompanySimple;
import com.company.cloud.company.modules.api.service.CompanyRemoteService;
import com.company.cloud.coupon.modules.api.request.CouponOrderItem;
import com.company.cloud.coupon.modules.api.request.Use2notCouponRequest;
import com.company.cloud.coupon.modules.api.request.UseCouponRequest;
import com.company.cloud.coupon.modules.api.response.UseCouponResponse;
import com.company.cloud.coupon.modules.api.service.CouponRemoteService;
import com.company.cloud.customer.modules.api.response.AddrResponse;
import com.company.cloud.customer.modules.api.service.CustomerRemoteService;
import com.company.cloud.mall.constant.MallErrorEnum;
import com.company.cloud.mall.constant.PayMethodEnum;
import com.company.cloud.mall.constant.ShippingMethodEnum;
import com.company.cloud.mall.constant.ShopConstant.OrderTypeEnum;
import com.company.cloud.mall.modules.api.constant.OrderStateEnum;
import com.company.cloud.mall.modules.api.constant.OrderTicketStateEnum;
import com.company.cloud.mall.modules.api.response.OrderAfterModel;
import com.company.cloud.mall.modules.api.response.OrderModel;
import com.company.cloud.mall.modules.app.controller.req.OrderByProductSingleSaveParam;
import com.company.cloud.mall.modules.app.controller.req.OrderExchangeParam;
import com.company.cloud.mall.modules.app.controller.req.OrderQuery4PageParam;
import com.company.cloud.mall.modules.app.controller.req.OrderSaveItem;
import com.company.cloud.mall.modules.app.controller.req.OrderSaveParam;
import com.company.cloud.mall.modules.app.controller.req.OrderSaveProductItem;
import com.company.cloud.mall.modules.app.controller.req.OrderTicketCodeCheckParam;
import com.company.cloud.mall.modules.app.service.ShopOrderService;
import com.company.cloud.mall.modules.app.utils.AfterOrderUtil;
import com.company.cloud.mall.modules.base.entity.OrderInfo;
import com.company.cloud.mall.modules.base.entity.OrderItem;
import com.company.cloud.mall.modules.base.entity.OrderItemTicketCode;
import com.company.cloud.mall.modules.base.entity.OrderPayment;
import com.company.cloud.mall.modules.base.entity.OrderRefunds;
import com.company.cloud.mall.modules.base.entity.OrderReturns;
import com.company.cloud.mall.modules.base.entity.OrderShipping;
import com.company.cloud.mall.modules.base.entity.OrderShippingItem;
import com.company.cloud.mall.modules.base.service.CartInfoService;
import com.company.cloud.mall.modules.base.service.OrderInfoService;
import com.company.cloud.mall.modules.base.service.OrderItemService;
import com.company.cloud.mall.modules.base.service.OrderItemTicketCodeService;
import com.company.cloud.mall.modules.base.service.OrderPaymentService;
import com.company.cloud.mall.modules.base.service.OrderRefundsService;
import com.company.cloud.mall.modules.base.service.OrderReturnsService;
import com.company.cloud.mall.modules.base.service.OrderShippingItemService;
import com.company.cloud.mall.modules.base.service.OrderShippingService;
import com.company.cloud.mall.modules.bus.producer.ShopOrderProducer;
import com.company.cloud.mall.modules.cache.models.FrameModel;
import com.company.cloud.mall.modules.cache.service.ShopOrderCacheService;
import com.company.cloud.mall.modules.mgr.controller.req.OrderMgrQuery4PageParam;
import com.company.cloud.mall.modules.mgr.controller.req.OrderSendParam;
import com.company.cloud.mall.modules.utils.ShopNoUtils;
import com.company.cloud.mall.modules.utils.ShopOrderConvertUtils;
import com.company.cloud.pay.modules.api.constant.PayStateEnum;
import com.company.cloud.product.modules.api.constant.ProductStockBusiTypeEnum;
import com.company.cloud.product.modules.api.constant.ProductTwoTypeEnum;
import com.company.cloud.product.modules.api.constant.ProductTypeEnum;
import com.company.cloud.product.modules.api.request.ProductStockMultipleSkuItem;
import com.company.cloud.product.modules.api.request.ProductStockMultipleSkuOpParam;
import com.company.cloud.product.modules.api.response.Sku;
import com.company.cloud.product.modules.api.service.ProductRemoteService;
import com.company.cloud.product.modules.api.service.ProductStoctRemoteService;
import com.company.cloud.user.modules.api.response.UserSimple;
import com.company.cloud.user.modules.api.service.UserRemoteService;
import com.company.common.server.constant.IRelBusiType;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;

@Service
public class ShopOrderServiceImpl implements ShopOrderService {

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private CustomerRemoteService customerRemoteService;

    @Autowired
    private ProductRemoteService productRemoteService;

    @Autowired
    private UserRemoteService userRemoteService;

    @Autowired
    private CartInfoService cartInfoService;

    @Autowired
    private OrderShippingService orderShippingService;

    @Autowired
    private OrderShippingItemService orderShippingItemService;

    @Autowired
    private ProductStoctRemoteService productStoctRemoteService;

    @Autowired
    private OrderPaymentService orderPaymentService;

    @Autowired
    private AccountRemoteService accountRemoteService;

    @Autowired
    private CouponRemoteService couponRemoteService;

    @Autowired
    private OrderRefundsService orderRefundsService;

    @Autowired
    private OrderReturnsService orderReturnsService;

    @Autowired
    private CompanyRemoteService companyRemoteService;

    @Autowired
    private OrderItemTicketCodeService orderItemTicketCodeService;

    @Autowired
    private ShopOrderProducer shopOrderProducer;

    @Autowired
    private ShopOrderCacheService shopOrderCacheService;

    @Autowired
    private ArtArtistRemoteService artArtistRemoteService;

    /**
     * @param isItemInfo      :是否取明细
     * @param isAfter:是否取售后信息
     * @param isCompanyInfo   :是否取公司信息
     * @param isUserInfo      :是否取用户信息
     */
    private IPage<OrderModel> getOrderModel(IPage<OrderInfo> page, boolean isItemInfo, boolean isAfter,
                                            boolean isCompanyInfo, boolean isUserInfo) {

        Set<String> snList = new HashSet<String>();
        Set<String> companyNos = new HashSet<String>();
        Set<Integer> userIds = new HashSet<Integer>();
        page.getRecords().forEach(item -> {
            if (isItemInfo) {
                snList.add(item.getSn());
            }
            if (isCompanyInfo) {
                companyNos.add(item.getCompanyNo());
            }
            if (isUserInfo) {
                userIds.add(item.getUserId());
            }
        });

        //订单明细
        List<OrderItem> orderItemList;
        Map<Integer, OrderAfterModel> afterMap;
        if (isItemInfo) {
            orderItemList = orderItemService.list(new QueryWrapper<OrderItem>().in("order_sn", snList));
        } else {
            orderItemList = new ArrayList<OrderItem>();
        }

        // 艺术家明细
        Map<String, Artist> artistMap = new HashMap<>();
        orderItemList.forEach(orderItem -> {
            String productNo = orderItem.getProductNo();
            BaseClientResult<Product> productResult = productRemoteService.getProductByDbById(productNo);
            if (CheckUtils.hasClientResult(productResult)) {
                Product product = productResult.getData();
                String bizValue4 = product.getBizValue4();
                BaseClientResult<Artist> artistBaseClientResp = artArtistRemoteService.artistInfo(bizValue4);
                if (CheckUtils.hasClientResult(artistBaseClientResp)) {
                    Artist artist = artistBaseClientResp.getData();
                    if (artist != null) {
                        artistMap.put(productNo, artist);
                    }
                }
            }
        });

        //退货明细
        if (isItemInfo && isAfter) {
            List<OrderRefunds> orderRefundsList = orderRefundsService
                    .list(new QueryWrapper<OrderRefunds>().in("order_sn", snList));
            List<OrderReturns> orderReturnsList = orderReturnsService
                    .list(new QueryWrapper<OrderReturns>().in("order_sn", snList));
            afterMap = AfterOrderUtil.getLastAfterByOrderItem(orderRefundsList, orderReturnsList);
        } else {
            afterMap = null;
        }

        //用户
        Map<Integer, UserSimple> userMap;
        if (isUserInfo) {
            BaseClientResult<Map<Integer, UserSimple>> userResp = userRemoteService.getUserMapByIds(userIds);
            userMap = BaseClientResult.getResultData(userResp, new HashMap<Integer, UserSimple>());
        } else {
            userMap = new HashMap<Integer, UserSimple>();
        }

        //公司
        Map<String, CompanySimple> companyMap;
        if (isCompanyInfo) {
            BaseClientResult<Map<String, CompanySimple>> companySimpleResp = companyRemoteService.getCompanyMapSimple(companyNos);
            if (CheckUtils.hasClientResult(companySimpleResp)) {
                companyMap = companySimpleResp.getData();
            } else {
                companyMap = new HashMap<String, CompanySimple>();
            }
        } else {
            companyMap = new HashMap<String, CompanySimple>();
        }

        IPage<OrderModel> data = page.convert(new Function<OrderInfo, OrderModel>() {
            @Override
            public OrderModel apply(OrderInfo entity) {
                return ShopOrderConvertUtils.getOrderModel(entity, orderItemList, null, afterMap, userMap, companyMap, artistMap);
            }
        });
        return data;
    }

    @Override
    public OrderModel getOrder(String sn, boolean isCompany, boolean isUser, boolean isPay, boolean isSend, boolean isAfter) {
        return this.getOrder(sn, null, isCompany, isUser, isPay, isSend, isAfter);
    }

    @Override
    public OrderModel getOrder(String sn, Integer itemId, boolean isCompany, boolean isUser, boolean isPay,
                               boolean isSend, boolean isAfter) {
        OrderInfo entity = orderInfoService.getById(sn);
        if (null == entity) {
            throw new BusinessException(MallErrorEnum.Order_Null);
        }
        List<OrderItem> items = orderItemService
                .list(new QueryWrapper<OrderItem>().eq("order_sn", sn).eq(CheckUtils.hasInt(itemId), "ID", itemId));

        List<OrderItemTicketCode> ticketCodes = orderItemTicketCodeService.list(new QueryWrapper<OrderItemTicketCode>()
                .eq("order_sn", sn));

        OrderModel data = null;
        // 售后信息
        if (isAfter) {
            List<OrderRefunds> refundList = orderRefundsService
                    .list(new QueryWrapper<OrderRefunds>().eq("order_sn", sn));
            List<OrderReturns> returnList = orderReturnsService
                    .list(new QueryWrapper<OrderReturns>().eq("order_sn", sn));

            Map<Integer, OrderAfterModel> lastAfterMap = AfterOrderUtil.getLastAfterByOrderItem(refundList, returnList);
            data = ShopOrderConvertUtils.getOrderModel(entity, items, ticketCodes, null, lastAfterMap, refundList, returnList);
        } else {
            data = ShopOrderConvertUtils.getOrderModel(entity, items, ticketCodes, null, null, null, new HashMap<>());
        }


        // 公司信息
        if (isCompany) {
            BaseClientResult<CompanySimple> company = companyRemoteService.getCompanySimple(entity.getCompanyNo());
            if (CheckUtils.hasClientResult(company)) {
                data.setCompanyName(company.getData() == null ? null : company.getData().getName());
            }
        }

        // 用户信息
        if (isUser) {
            BaseClientResult<UserSimple> userSimpleResp = userRemoteService.getUserById(entity.getUserId());
            UserSimple user = BaseClientResult.getResultData(userSimpleResp);
            if (user != null) {
                data.setUserName(user.getUserName());
                data.setUserNickName(user.getNickName());
                data.setUserRealName(user.getRealName());
                data.setUserHeadImg(user.getHeadImg());
            }
        }

        // 支付信息
        if (isPay) {
            List<OrderPayment> payList = orderPaymentService.list(new QueryWrapper<OrderPayment>()
                    .eq("biz_order_type", IRelBusiType.Order_ObjType).eq("biz_order_sn", sn));
            if (!CollectionUtils.isEmpty(payList)) {
                for (OrderPayment pay : payList) {
                    data.addItem(ShopOrderConvertUtils.getOrderPay(pay));
                }
            }
        }

        // 发货信息
        if (isSend) {
            List<OrderShipping> orderShippingList = orderShippingService
                    .list(new QueryWrapper<OrderShipping>().eq("order_sn", sn).orderByDesc("cdt"));
            if (!CollectionUtils.isEmpty(orderShippingList)) {
                for (OrderShipping item : orderShippingList) {
                    data.addItem(ShopOrderConvertUtils.getOrderShipping(item));
                }
            }
        }

        return data;
    }

    @Override
    public IPage<OrderModel> queryUserOrders(OrderQuery4PageParam params, LoginSimpleUserInfo userInfo) {
        IPage<OrderInfo> page = orderInfoService.page(new Page<>(params.getPage(), params.getRows()),
                new QueryWrapper<OrderInfo>()
//						.eq("company_no", userInfo.getCompanyNo())
                        .eq(StringUtils.hasText(params.getBusiNo()), "busi_no", params.getBusiNo())
                        .eq(CheckUtils.hasInt(params.getUserId()), "user_id", params.getUserId())
                        .eq(CheckUtils.hasInt(params.getReferralUserId()), "referral_user_id", params.getReferralUserId())
                        .eq(StringUtils.hasText(params.getStatus()), "status", params.getStatus())
                        .eq(StringUtils.hasText(params.getOrderType()), "order_type", params.getOrderType())
                        .eq(StringUtils.hasText(params.getUserDelState()), "user_del_state", params.getUserDelState())
                        .orderByDesc("order_date"));
        if (page == null || CollectionUtils.isEmpty(page.getRecords())) {
            return null;
        }
        return this.getOrderModel(page, params.isItem(), params.isAfter(), params.isBusiness(), params.isUser());
    }

    @Override
    public IPage<OrderModel> queryOrders(OrderMgrQuery4PageParam params, LoginSimpleUserInfo userInfo) {
        IPage<OrderInfo> page = orderInfoService.page(new Page<>(params.getPage(), params.getRows()),
                new QueryWrapper<OrderInfo>()
//				.eq(ProjectUtils.getComColName(), ProjectUtils.getComColVal(userInfo))
                        .eq(StringUtils.hasText(params.getCompanyNo()), "company_no", params.getCompanyNo())
                        .eq(StringUtils.hasText(params.getMainCompanyNo()), "main_company_no",
                                params.getMainCompanyNo())
//						.apply(StringUtils.hasText(params.getIsAgent()), "company_no<>main_company_no")
                        .eq(StringUtils.hasText(params.getSn()), "sn", params.getSn())
                        .eq(CheckUtils.hasInt(params.getUserId()), "user_id", params.getUserId())
                        .eq(StringUtils.hasText(params.getStatus()), "status", params.getStatus())
                        .eq(StringUtils.hasText(params.getOrderType()), "order_type", params.getOrderType())
                        .orderByDesc("order_date"));
        if (page == null || CollectionUtils.isEmpty(page.getRecords())) {
            return null;
        }
        return this.getOrderModel(page, params.isItem(), params.isAfter(), params.isBusiness(), params.isUser());
    }

    @Transactional
    @Override
    public List<OrderInfo> saveOrderByCustMultiple(Integer userId, Integer referralUserId, String referralCode,
                                                   OrderSaveParam params, LoginSimpleUserInfo userInfo) {
        List<OrderInfo> orderList = new ArrayList<OrderInfo>();
        System.out.println("======== orders =" + params.getOrders().size());
        for (OrderSaveItem item : params.getOrders()) {
            if (item != null) {
                OrderInfo order = this.saveOrder(userId, referralUserId, referralCode, item, userInfo);
                orderList.add(order);
            }
        }
        return orderList;
    }

    @Transactional
    @Override
    public OrderInfo saveOrderByProductSingle(Integer userId, Integer referralUserId, String referralCode,
                                              OrderByProductSingleSaveParam params, LoginSimpleUserInfo userInfo) {

        OrderSaveItem item = new OrderSaveItem();
        item.setAddrId(params.getAddrId());
        item.setShippingMethod(params.getShippingMethod());
        item.setFreight(params.getFreight());
        item.setCouponCode(params.getCouponCode());
//		item.setCouponDiscountFund(params.getCouponDiscountFund());
        item.setUserMemo(params.getUserMemo());
        item.setIsInvoice(params.getIsInvoice());
        item.setInvoiceType(params.getInvoiceType());
        item.setInvoiceTitle(params.getInvoiceTitle());
        item.setInvoiceTaxNo(params.getInvoiceTaxNo());
        item.setInvoiceContent(params.getInvoiceContent());
        item.setUseUserMobile(params.getUseUserMobile());
        item.setUseUserName(params.getUseUserName());
        item.setOrderParam(params.getOrderParam());
        item.addItem(new OrderSaveProductItem(params.getProductNo(), params.getSkuNo(), params.getFrameNo(), params.getQuantity(),
                params.getCartId()));
        return this.saveOrder(userId, referralUserId, referralCode, item, userInfo);
    }

    @Transactional
    @Override
    public OrderInfo saveOrderByCustSingle(Integer userId, Integer referralUserId, String referralCode,
                                           OrderSaveItem params, LoginSimpleUserInfo userInfo) {
        return this.saveOrder(userId, referralUserId, referralCode, params, userInfo);
    }

    private OrderInfo saveOrder(Integer userId, Integer referralUserId, String referralCode, OrderSaveItem params,
                                LoginSimpleUserInfo userInfo) {
        String sn = ShopNoUtils.getOrderSn();
        Set<String> skuNoSet = new HashSet<String>();
        params.getItems().forEach(item -> {
            skuNoSet.add(item.getSkuNo());
        });

        //框子
        Map<String, FrameModel> frameMap = shopOrderCacheService.getFrameMap();

        BaseClientResult<Map<String, Sku>> skuResp = productRemoteService.getSkuMapByDbByNos(skuNoSet);
        Map<String, Sku> skuMap = BaseClientResult.getResultData(skuResp);
        List<OrderItem> orderItemList = new ArrayList<OrderItem>();
        List<Integer> cartIdList = new ArrayList<Integer>();

        String companyNo = null;                    // 公司编号
        String mainCompanyNo = null;                // 主公司编号
//		String busiNo = null;                       // 商户编号
        BigDecimal productFund = BigDecimal.ZERO;   // 商品金额
        Integer exchangePoint = 0;                  // 兑换积分
        Integer rewardPoint = 0;                    // 赠送积分
        boolean isDis = false;

        String twoType = null;
        ProductStockMultipleSkuOpParam stockParams = new ProductStockMultipleSkuOpParam(); //库存
        List<OrderItemTicketCode> ticketCodeList = new ArrayList<OrderItemTicketCode>(); //兑换码
        for (OrderSaveProductItem item : params.getItems()) {
            Sku sku = skuMap.get(item.getSkuNo());
            if (sku != null) {
                System.out.println("=============sku.getType()====="+sku.getType()+"========================"+sku.getType());
                // 判断是否交易型商品
                if (!Objects.equals(ProductTypeEnum.Trade_Product.getCode(),sku.getType()) &&
                        !Objects.equals(ProductTypeEnum.Un_Trade_Product.getCode(),sku.getType())) {
                    throw new BusinessException(MallErrorEnum.Order_Not_Trade_Product);
                }

                // 判断商品二级类型是否一致
                if (StringUtils.isEmpty(twoType)) {
                    twoType = sku.getTwoType();
                } else {
                    if (!twoType.equals(sku.getTwoType())) {
                        throw new BusinessException(MallErrorEnum.Order_NotSave_Product_Type);
                    }
                }

                // 判断公司是否一致
                if (StringUtils.isEmpty(companyNo)) {
                    companyNo = sku.getCompanyNo();
                } else {
                    if (!companyNo.equals(sku.getCompanyNo())) {
                        throw new BusinessException(MallErrorEnum.Order_NotSave_Product_Business);
                    }
                }

                // 判断主公司是否一致
                if (StringUtils.isEmpty(mainCompanyNo)) {
                    mainCompanyNo = sku.getMainCompanyNo();
                } else {
                    if (!mainCompanyNo.equals(sku.getMainCompanyNo())) {
                        throw new BusinessException(MallErrorEnum.Order_NotSave_Product_Business);
                    }
                }

                //判断商品是否支持分销
                if (StringUtils.hasText(sku.getIsDis()) && YNEnum.YES.getCode().equals(sku.getIsDis())) {
                    isDis = true;
                }
                FrameModel frame = null;
                if (StrUtil.isNotEmpty(item.getFrameNo())) {
                    frame = frameMap.get(item.getFrameNo());
                    if (frame == null) {
                        throw new BusinessException(BaseReturnEnum.PARAM_ERROR, "裱框不存在");
                    }
                    if (frame.getPrice().doubleValue() <= 0) {
                        throw new BusinessException(BaseReturnEnum.PARAM_ERROR, "裱框价格错误");
                    }
                }

                if (sku.getPrice().doubleValue() <= 0) {
                    throw new BusinessException(BaseReturnEnum.PARAM_ERROR, "商品价格错误");
                }

                if (item.getQuantity() <= 0) {
                    throw new BusinessException(BaseReturnEnum.PARAM_ERROR, "商品数量错误");
                }

                OrderItem orderItem = new OrderItem();
                orderItem.setOrderSn(sn);
                orderItem.setProductNo(sku.getProductNo());
                orderItem.setMainProductNo(sku.getMainProductNo());
                orderItem.setSkuNo(sku.getSkuNo());
                orderItem.setMainSkuNo(sku.getMainSkuNo());
                orderItem.setIsDisProduct(sku.getIsDis());
                orderItem.setName(sku.getName());
                orderItem.setThumbnail(sku.getImage());
                orderItem.setSpecifications(sku.getSpecificationValues());
                if (frame != null) {
                    orderItem.setFrameNo(frame.getCode());
                    orderItem.setFrameName(frame.getName());
                    orderItem.setFrameImage(frame.getImage());
                    orderItem.setFramePrice(frame.getPrice());
                } else {
                    orderItem.setFramePrice(BigDecimal.ZERO);
                }
                orderItem.setExtendOne(item.getExtendOne());
                orderItem.setExtendTwo(item.getExtendTwo());
                orderItem.setExtendThree(item.getExtendThree());
                orderItem.setPrice(sku.getPrice().add(orderItem.getFramePrice()));
                orderItem.setQuantity(item.getQuantity());
                orderItem.setShippedQuantity(0);
                orderItem.setReturnedQuantity(0);
                orderItem.setReturnedNotSendQuantity(0);
                orderItem.setIsExchangePurchase(sku.getIsExchangePurchase());
                orderItem.addCreateParam(userInfo);
                orderItemList.add(orderItem);

                if (CheckUtils.hasInt(item.getCartId())) {
                    cartIdList.add(item.getCartId());
                }

                stockParams.addItem(new ProductStockMultipleSkuItem(item.getSkuNo(), item.getQuantity()));

                productFund = productFund.add(orderItem.getPrice().multiply(new BigDecimal(item.getQuantity())));

                if (sku.getExchangePoint() != null && sku.getExchangePoint() > 0) {
                    exchangePoint = exchangePoint + (sku.getExchangePoint() * item.getQuantity());
                }

                if (sku.getRewardPoint() != null && sku.getRewardPoint() > 0) {
                    rewardPoint = rewardPoint + (sku.getRewardPoint() * item.getQuantity());
                }
            }
        }

        //
        OrderInfo order = new OrderInfo();
        order.setSn(sn);
        order.setUserId(userId);
        order.setReferralCode(referralCode);
        order.setReferralUserId(referralUserId);
        order.setCompanyNo(companyNo);
        order.setMainCompanyNo(mainCompanyNo);
        order.setOrderDate(LocalDateTime.now());
        order.setOrderExpire(LocalDateTime.now().plusDays(1)); // 过期时间1天
        // 配送方式
        if (StringUtils.isEmpty(params.getShippingMethod())) {
            params.setShippingMethod(ShippingMethodEnum.General_Shipping.getCode());
        }

        AddrResponse addr = null;
        // 订单分类
        if (ProductTwoTypeEnum.Trade_Regular_Product.getCode().equals(twoType)) {// 普通订单
            order.setOrderType(OrderTypeEnum.OT_General.getCode());
            if (params.getAddrId() == null) {
                throw new BusinessException(MallErrorEnum.Order_Addr_Null);
            }
            //todo
            BaseClientResult<AddrResponse> addrRespResult = customerRemoteService.getAddrById(params.getAddrId());
            addr = BaseClientResult.getResultData(addrRespResult);
            if (addr == null) {
                throw new BusinessException(MallErrorEnum.Order_Addr_Null);
            }
        } else if (ProductTwoTypeEnum.Trade_Point_Product.getCode().equals(twoType)) {// 积分订单
            if (orderItemList.size() > 1) {
                throw new BusinessException(MallErrorEnum.Order_Op_UnderLine_One);
            }
            if (params.getAddrId() == null) {
                throw new BusinessException(MallErrorEnum.Order_Addr_Null);
            }
            //todo
            BaseClientResult<AddrResponse> addrRespResult = customerRemoteService.getAddrById(params.getAddrId());
            addr = BaseClientResult.getResultData(addrRespResult);
            if (addr == null) {
                throw new BusinessException(MallErrorEnum.Order_Addr_Null);
            }
            order.setOrderType(OrderTypeEnum.OT_Point.getCode());
        } else if (ProductTwoTypeEnum.Trade_UnderExchange_Product.getCode().equals(twoType)) {// 线下服务订单
            if (orderItemList.size() > 1) {
                throw new BusinessException(MallErrorEnum.Order_Op_UnderLine_One);
            }
            order.setOrderType(OrderTypeEnum.OT_UnderLine.getCode());
            params.setShippingMethod(ShippingMethodEnum.Shop_Consume.getCode());
            order.setExchangeCode(ShopNoUtils.getOrderExchangeCode());
        } else if (ProductTwoTypeEnum.Trade_Ticket_Product.getCode().equals(twoType)) {// 核销订单
            if (orderItemList.size() > 1) {
                throw new BusinessException(MallErrorEnum.Order_Op_UnderLine_One);
            }
            order.setOrderType(OrderTypeEnum.OT_Ticket.getCode());
            params.setShippingMethod(ShippingMethodEnum.Shop_Consume.getCode());
            //生成核销码
            for (OrderItem orderItem : orderItemList) {
                for (int i = 0; i < orderItem.getQuantity(); i++) {
                    OrderItemTicketCode oitc = new OrderItemTicketCode();
                    oitc.setOrderSn(order.getSn());
                    oitc.setProductType(orderItem.getProductType());
                    oitc.setProductNo(orderItem.getProductNo());
                    oitc.setTicketCode(IdUtil.getSnowflake(8, 8).nextIdStr());
                    oitc.setState(OrderTicketStateEnum.Not_Use.getCode());
                    oitc.setProvideDt(LocalDateTime.now());
                    oitc.setProviderUserId(userInfo.getId());
                    oitc.addCreateParam(userInfo);
                    oitc.addEditParam(userInfo);
                    ticketCodeList.add(oitc);
                }
            }

        }

        // 积分
        order.setIsExchangePoint(YNEnum.NO.getCode());
        order.setExchangePoint(exchangePoint);
        order.setIsRewardPoint(YNEnum.NO.getCode());
        order.setRewardPoint(rewardPoint);

        // 优惠券
        if (StringUtils.isEmpty(params.getCouponCode())) {
            order.setIsUseCouponCode(YNEnum.NO.getCode());
            order.setCouponDiscountFund(BigDecimal.ZERO);
        } else {
            // 非积分订单
            if (!ProductTwoTypeEnum.Trade_Point_Product.getCode().equals(twoType)) {
                // 使用优惠券
                List<CouponOrderItem> coItems = this.getCouponOrderItem(orderItemList);
                BaseClientResult<UseCouponResponse> useCouponResponseResult = couponRemoteService.useCoupon(new UseCouponRequest(params.getCouponCode(), coItems, userInfo));
                UseCouponResponse useCouponResponse = BaseClientResult.getResultData2Error(useCouponResponseResult);
                order.setIsUseCouponCode(YNEnum.YES.getCode());
                order.setCouponCode(params.getCouponCode());
                order.setCouponDiscountFund(useCouponResponse.getFund());
            }
        }

        // 配送
        order.setShippingMethod(params.getShippingMethod());
        if (params.getFreight() == null) {
            order.setFreight(BigDecimal.ZERO);
        } else {
            if (params.getFreight().doubleValue() < 0) {
                throw new BusinessException(BaseReturnEnum.PARAM_ERROR.getCode(), "运费不能小于0");
            }
            order.setFreight(params.getFreight());
        }
        if (addr != null) {
            order.setConsigneeName(addr.getLinkManName());
            order.setConsigneePhone(addr.getLinkManMobile());
            order.setConsigneeProvince(addr.getProvince());
            order.setConsigneeCity(addr.getCity());
            order.setConsigneeRegion(addr.getRegion());
            order.setConsigneeStreet(addr.getStreet());
            order.setConsigneeAddr(addr.getAddr());
        }
        // 发票
        order.setIsInvoice(params.getIsInvoice());
        order.setInvoiceType(params.getInvoiceType());
        order.setInvoiceTaxNo(params.getInvoiceTaxNo());
        order.setInvoiceTitle(params.getInvoiceTitle());
        order.setInvoiceContent(params.getInvoiceContent());
        order.setIsAllocatedStock(YNEnum.YES.getCode());

        // 支付
        if (ProductTwoTypeEnum.Trade_Point_Product.getCode().equals(twoType)) {
            order.setPaymentMethod(PayMethodEnum.PM_Point_Pay.getCode());
        }
        order.setPaymentFund(BigDecimal.ZERO);
        order.setPaymentFee(BigDecimal.ZERO);
        order.setPaymentState(PayStateEnum.Pay_Not.getCode());

        // 商品金额
        order.setProductFund(productFund);
        if (order.getCouponDiscountFund() == null) {
            order.setCouponDiscountFund(BigDecimal.ZERO);
        }
        // 订单金额
        BigDecimal orderFund = order.getProductFund().add(order.getPaymentFee()).add(order.getFreight())
                .subtract(order.getCouponDiscountFund());
        if (orderFund.doubleValue() > 0) {
            order.setFund(orderFund);
        } else {
            order.setFund(BigDecimal.ZERO);
        }

        // 根据订单金额计算订单状态
        if (order.getFund().doubleValue() > 0) {
            order.setStatus(OrderStateEnum.OSE_Pay.getCode());
        } else {
            order.setStatus(OrderStateEnum.OSE_Send.getCode());
        }
        // 退款金额
        order.setRefundFund(BigDecimal.ZERO);

        // 其它参数
        order.setUserMemo(params.getUserMemo());
        order.setUseUserMobile(params.getUseUserMobile());
        order.setUseUserName(params.getUseUserName());
        if (params.getOrderParam() != null) {
            order.setOrderParam(JSON.toJSONString(params.getOrderParam()));
        }
        order.setIsDisProduct(isDis ? YNEnum.YES.getCode() : YNEnum.NO.getCode());
        order.setUserDelState(YNEnum.YES.getCode());
        // 库存
        stockParams.setCompanyNo(order.getMainCompanyNo());
        stockParams.setBusiType(ProductStockBusiTypeEnum.PSBT_Out_Freeze.getCode());
        stockParams.setOpUserInfo(userInfo);
        productStoctRemoteService.opMultipleSkuStock(stockParams);

        orderInfoService.save(order);
        orderItemService.saveBatch(orderItemList);
        if (ticketCodeList.size() > 0) {
            orderItemTicketCodeService.saveBatch(ticketCodeList);
        }

        if (cartIdList.size() > 0) {
            cartInfoService.removeByIds(cartIdList);
        }
        shopOrderProducer.onOrderChange(order, orderItemList);
        return order;
    }

    private List<CouponOrderItem> getCouponOrderItem(List<OrderItem> orderItemList) {
        List<CouponOrderItem> items = new ArrayList<CouponOrderItem>();
        orderItemList.forEach(orderItem -> {
            items.add(new CouponOrderItem(orderItem.getProductNo(), orderItem.getSkuNo(), null, orderItem.getPrice(),
                    orderItem.getQuantity()));
        });
        return items;
    }

    /**
     * 关闭
     */
    @Transactional
    @Override
    public void close(String sn, LoginSimpleUserInfo userInfo) {
        OrderInfo entity = orderInfoService.getById(sn);
        if (entity == null) {
            throw new BusinessException(MallErrorEnum.Order_Null);
        }
        if (userInfo.getId().intValue() != entity.getUserId().intValue()) {
            throw new BusinessException(MallErrorEnum.Order_User_Error);
        }
        if (!OrderStateEnum.OSE_Pay.getCode().equals(entity.getStatus())) {
            throw new BusinessException(MallErrorEnum.Order_Op_State);
        }
        entity.setStatus(OrderStateEnum.OSE_Close.getCode());
        entity.setCloseDate(LocalDateTime.now());
        entity.setHandleDate(LocalDateTime.now());
        entity.setHandleUserId(userInfo.getId());
        entity.addEditParam(userInfo);

        List<OrderItem> orderItems = orderItemService.list(new QueryWrapper<OrderItem>().eq("order_sn", sn));

        if (YNEnum.YES.getCode().equals(entity.getIsAllocatedStock())) {
            ProductStockMultipleSkuOpParam stockParams = new ProductStockMultipleSkuOpParam();
            orderItems.forEach(item -> {
                stockParams.addItem(new ProductStockMultipleSkuItem(item.getSkuNo(), item.getQuantity()));
            });
            stockParams.setBusiType(ProductStockBusiTypeEnum.PSBT_Out_Defreeze.getCode());
            productStoctRemoteService.opMultipleSkuStock(stockParams);
        }
        //
        if (StringUtils.hasText(entity.getCouponCode())) {
            couponRemoteService.use2notCoupon(new Use2notCouponRequest(entity.getCouponCode(), userInfo));
        }
        orderInfoService.updateById(entity);
        //MQ
        shopOrderProducer.onOrderChange(entity, orderItems);
    }

    /**
     * 审核
     */
    @Transactional
    @Override
    public void check(String sn, YNEnum state, LoginSimpleUserInfo userInfo) {
        OrderInfo entity = orderInfoService.getById(sn);
        if (entity == null) {
            throw new BusinessException(MallErrorEnum.Order_Null);
        }
        if (!userInfo.getCompanyNo().equals(entity.getMainCompanyNo())) {
            throw new BusinessException(MallErrorEnum.Order_User_Error);
        }
        if (!OrderStateEnum.OSE_Check.getCode().equals(entity.getStatus())) {
            throw new BusinessException(MallErrorEnum.Order_Op_State);
        }
        if (YNEnum.YES == state) {
            entity.setStatus(OrderStateEnum.OSE_Send.getCode());
        } else {
            entity.setStatus(OrderStateEnum.OSE_Close.getCode());
        }
        entity.setCheckDate(LocalDateTime.now());
        entity.setHandleDate(LocalDateTime.now());
        entity.setHandleUserId(userInfo.getId());
        entity.addEditParam(userInfo);
        if (YNEnum.YES.getCode().equals(entity.getIsAllocatedStock())) {
            ProductStockMultipleSkuOpParam stockParams = new ProductStockMultipleSkuOpParam();
            List<OrderItem> orderItems = orderItemService.list(new QueryWrapper<OrderItem>().eq("order_sn", sn));
            orderItems.forEach(item -> {
                stockParams.addItem(new ProductStockMultipleSkuItem(item.getSkuNo(), item.getQuantity()));
            });
            stockParams.setBusiType(ProductStockBusiTypeEnum.PSBT_Out_Defreeze.getCode());
            productStoctRemoteService.opMultipleSkuStock(stockParams);
        }
        orderInfoService.updateById(entity);

        //MQ
        List<OrderItem> orderItemList = orderItemService
                .list(new QueryWrapper<OrderItem>().eq("order_sn", entity.getSn()));
        shopOrderProducer.onOrderChange(entity, orderItemList);
    }

    /**
     * 发货
     */
    @Transactional
    @Override
    public void send(OrderSendParam params, LoginSimpleUserInfo userInfo) {
        OrderInfo entity = orderInfoService.getById(params.getOrderSn());
        if (entity == null) {
            throw new BusinessException(MallErrorEnum.Order_Null);
        }
        //fangjun 2022/06/22   update
      /*  if (!userInfo.getCompanyNo().equals(entity.getMainCompanyNo())) {
            throw new BusinessException(MallErrorEnum.Order_User_Error);
        }*/
        if (OrderStateEnum.OSE_Send.getCode().equals(entity.getStatus())
                || OrderStateEnum.OSE_Send_Part.getCode().equals(entity.getStatus())) {
        } else {
            throw new BusinessException(MallErrorEnum.Order_Op_State);
        }

        if (!ShippingMethodEnum.General_Shipping.getCode().equals(entity.getShippingMethod())) {
            throw new BusinessException(MallErrorEnum.Order_Op_ShippingMethod_Not);
        }

        List<OrderRefunds> orderRefundsList = orderRefundsService
                .list(new QueryWrapper<OrderRefunds>().eq("order_sn", entity.getSn()));
        List<OrderReturns> orderReturnsList = orderReturnsService
                .list(new QueryWrapper<OrderReturns>().eq("order_sn", entity.getSn()));
        if (!AfterOrderUtil.validateOrderIng(orderRefundsList, orderReturnsList)) {
            throw new BusinessException(MallErrorEnum.Order_After_Ing);
        }

        // 订单明细
        Map<Integer, OrderItem> orderItemMap = new HashMap<Integer, OrderItem>();
        List<OrderItem> orderItemList = orderItemService
                .list(new QueryWrapper<OrderItem>().eq("order_sn", params.getOrderSn()));
        orderItemList.forEach(item -> {
            if (item.getQuantity().intValue() != item.getShippedQuantity().intValue()) {
                orderItemMap.put(item.getId(), item);
            }
        });

        String sn = ShopNoUtils.getShippingOrderSn();
        List<OrderItem> orderItems = new ArrayList<OrderItem>();
        List<OrderShippingItem> shippingItems = new ArrayList<OrderShippingItem>();
        ProductStockMultipleSkuOpParam stockParams = new ProductStockMultipleSkuOpParam();

        params.getItems().forEach(item -> {
            OrderItem orderItem = orderItemMap.get(item.getOrderItemId());
            if (orderItem == null) {
                throw new BusinessException(MallErrorEnum.OrderItem_Null);
            }
            Integer needNum = orderItem.getQuantity() - orderItem.getShippedQuantity()
                    - orderItem.getReturnedNotSendQuantity();
            if (item.getQuantity() > needNum) {
                throw new BusinessException(MallErrorEnum.Order_ShippedQuantity);
            }
            orderItem.setShippedQuantity(orderItem.getShippedQuantity() + item.getQuantity());
            orderItem.addEditParam(userInfo);
            orderItems.add(orderItem);

            if (orderItem.getQuantity().intValue() == (orderItem.getShippedQuantity().intValue()
                    + orderItem.getReturnedNotSendQuantity().intValue())) {
                orderItemMap.remove(item.getOrderItemId());
            }

            OrderShippingItem osItem = new OrderShippingItem();
            osItem.setShippingSn(sn);
            osItem.setProductNo(orderItem.getProductNo());
            osItem.setSkuNo(orderItem.getSkuNo());
            osItem.setName(orderItem.getName());
            osItem.setThumbnail(orderItem.getThumbnail());
            osItem.setSpecifications(orderItem.getSpecifications());
            osItem.setQuantity(item.getQuantity());
            shippingItems.add(osItem);

            stockParams.addItem(new ProductStockMultipleSkuItem(orderItem.getSkuNo(), item.getQuantity()));
        });

        // 库存
        if (YNEnum.YES.getCode().equals(entity.getIsAllocatedStock())) {
            stockParams.setBusiType(ProductStockBusiTypeEnum.PSBT_Out_Freeze_Sub.getCode());
            productStoctRemoteService.opMultipleSkuStock(stockParams);
        }

        // 更新订单状态
        if (orderItemMap.keySet().size() > 0) {
            entity.setStatus(OrderStateEnum.OSE_Send_Part.getCode());
        } else {
            entity.setStatus(OrderStateEnum.OSE_Receiving.getCode());
        }
        entity.setShippingDate(LocalDateTime.now());
        entity.setHandleDate(LocalDateTime.now());
        entity.setHandleUserId(userInfo.getId());
        entity.addEditParam(userInfo);
        orderInfoService.updateById(entity);

        // 更新订单明细（发货数量）
        if (orderItems.size() > 0) {
            orderItemService.updateBatchById(orderItems);
        }

        // 新增发货单
        OrderShipping orderShipping = new OrderShipping();
        orderShipping.setSn(sn);
        orderShipping.setOrderSn(params.getOrderSn());
        orderShipping.setShippingMethod(entity.getShippingMethod());
        orderShipping.setTrackingNo(params.getTrackingNo());
        orderShipping.setDeliveryCorpName(params.getDeliveryCorpName());
        orderShipping.setDeliveryCorpCode(params.getDeliveryCorpCode());
        orderShipping.setFreight(params.getFreight());
        orderShipping.setMemo(params.getMemo());
        orderShipping.setConsigneeName(entity.getConsigneeName());
        orderShipping.setConsigneePhone(entity.getConsigneePhone());
        orderShipping.setConsigneeProvince(entity.getConsigneeProvince());
        orderShipping.setConsigneeCity(entity.getConsigneeCity());
        orderShipping.setConsigneeRegion(entity.getConsigneeRegion());
        orderShipping.setConsigneeStreet(entity.getConsigneeStreet());
        orderShipping.setConsigneeAddr(entity.getConsigneeAddr());
        orderShipping.setSendDate(LocalDateTime.now());
        orderShipping.addCreateParam(userInfo);
        orderShippingService.save(orderShipping);

        // 新增发货单明细
        if (shippingItems.size() > 0) {
            orderShippingItemService.saveOrUpdateBatch(shippingItems);
        }
        //MQ
        shopOrderProducer.onOrderChange(entity, orderItemList);
    }

    /**
     * 完成(确认收货)
     */
    @Transactional
    @Override
    public void complete(String sn, LoginSimpleUserInfo userInfo) {
        OrderInfo entity = orderInfoService.getById(sn);
        if (entity == null) {
            throw new BusinessException(MallErrorEnum.Order_Null);
        }
        if (userInfo.getId().intValue() != entity.getUserId().intValue()) {
            throw new BusinessException(MallErrorEnum.Order_User_Error);
        }
        if (!OrderStateEnum.OSE_Receiving.getCode().equals(entity.getStatus())) {
            throw new BusinessException(MallErrorEnum.Order_Op_State);
        }
        entity.setStatus(OrderStateEnum.OSE_Complete.getCode());
        entity.setCompleteDate(LocalDateTime.now());
        entity.setHandleDate(LocalDateTime.now());
        entity.setHandleUserId(userInfo.getId());
        entity.addEditParam(userInfo);
        orderInfoService.updateById(entity);

        if (entity.getRewardPoint() != null && entity.getRewardPoint() > 0) {
            AcctOpRequest pointParam = new AcctOpRequest();
            pointParam.setUserId(entity.getUserId());
            pointParam.setType(AcctTypeEnum.Point_Acct.getCode());
            pointParam.setIsAcctDetail(YNEnum.YES.getCode());
            pointParam.setOpType(AcctOpTypeEnum.Add_Acct.getCode());
            pointParam.setRelObjType(IRelBusiType.Order_ObjType);
            pointParam.setRelObjNo(entity.getSn());
            pointParam.setFundOp(new BigDecimal(entity.getRewardPoint()));
            pointParam.setFundTax(BigDecimal.ZERO);
            pointParam.setRelBizName("订单赠送积分");
            pointParam.setRelDate(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            pointParam.setBusiType("新增积分");
            pointParam.setMemo("订单赠送积分");
            pointParam.setOpIp(userInfo.getIp());
            pointParam.setOpUserId(userInfo.getId());
            accountRemoteService.opAcct(pointParam);


        }
        List<OrderItem> orderItems = orderItemService
                .list(new QueryWrapper<OrderItem>().eq("order_sn", entity.getSn()));
        //MQ
        shopOrderProducer.onOrderChange(entity, orderItems);

    }

    /**
     * 完成订单任务
     */
    @Override
    public void completeByTask(OrderInfo order, LoginSimpleUserInfo userInfo) {
        order.setStatus(OrderStateEnum.OSE_Complete.getCode());
        order.setCompleteDate(LocalDateTime.now());
        order.setHandleDate(LocalDateTime.now());
        order.setHandleUserId(userInfo.getId());
        order.addEditParam(userInfo);
        orderInfoService.updateById(order);

        if (order.getRewardPoint() != null && order.getRewardPoint() > 0) {
            AcctOpRequest pointParam = new AcctOpRequest();
            pointParam.setUserId(order.getUserId());
            pointParam.setType(AcctTypeEnum.Point_Acct.getCode());
            pointParam.setIsAcctDetail(YNEnum.YES.getCode());
            pointParam.setOpType(AcctOpTypeEnum.Add_Acct.getCode());
            pointParam.setRelObjType(IRelBusiType.Order_ObjType);
            pointParam.setRelObjNo(order.getSn());
            pointParam.setFundOp(new BigDecimal(order.getRewardPoint()));
            pointParam.setFundTax(BigDecimal.ZERO);
            pointParam.setRelBizName("订单赠送积分");
            pointParam.setRelDate(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            pointParam.setBusiType("新增积分");
            pointParam.setMemo("订单赠送积分");
            pointParam.setOpIp(userInfo.getIp());
            pointParam.setOpUserId(userInfo.getId());
            accountRemoteService.opAcct(pointParam);


        }
        List<OrderItem> orderItems = orderItemService.list(new QueryWrapper<OrderItem>().eq("order_sn", order.getSn()));
        //todo订单完成通知
//		ShopOrderProducer.sendOrder2Complete(order, orderItems);
    }

    /**
     * 关闭订单任务
     */
    @Override
    public void closeTask() {
        IPage<OrderInfo> page = orderInfoService.page(new Page<>(1, 100),
                new QueryWrapper<OrderInfo>().eq("status", OrderStateEnum.OSE_Check.getCode())
                        .lt("order_date", LocalDateTime.now()).orderByAsc("order_date"));
        if (page == null || CollectionUtils.isEmpty(page.getRecords())) {
            return;
        }
        page.getRecords().forEach(item -> {
            close(item.getSn(), null);
        });
    }

    /**
     * 发货(自提/到店)
     */
    @Transactional
    @Override
    public void send(OrderExchangeParam params, LoginSimpleUserInfo userInfo) {
        OrderInfo entity = orderInfoService.getById(params.getOrderSn());
        if (entity == null) {
            throw new BusinessException(MallErrorEnum.Order_Null);
        }
        if (!OrderStateEnum.OSE_Send.getCode().equals(entity.getStatus())) {
            throw new BusinessException(MallErrorEnum.Order_Op_State);
        }
        if (ShippingMethodEnum.Self_Mention.getCode().equals(entity.getShippingMethod())
                || ShippingMethodEnum.Shop_Consume.getCode().equals(entity.getShippingMethod())) {
        } else {
            throw new BusinessException(MallErrorEnum.Order_Op_ShippingMethod_Not);
        }
        if (!params.getExchangeCode().equals(entity.getExchangeCode())) {
            throw new BusinessException(MallErrorEnum.Order_ExchangeCode_Error);
        }

        if (!userInfo.getCompanyNo().equals(entity.getMainCompanyNo())) {
            throw new BusinessException(MallErrorEnum.Order_Op_Business_Error);
        }

        List<OrderItem> orderItemList = orderItemService
                .list(new QueryWrapper<OrderItem>().eq("order_sn", params.getOrderSn()));

        ProductStockMultipleSkuOpParam stockParams = new ProductStockMultipleSkuOpParam();
        List<OrderItem> orderItemUpdateList = new ArrayList<OrderItem>();
        orderItemList.forEach(item -> {
            stockParams.addItem(new ProductStockMultipleSkuItem(item.getSkuNo(), item.getQuantity()));
            item.setShippedQuantity(item.getQuantity());
            orderItemUpdateList.add(item);
        });

        // 库存
        if (YNEnum.YES.getCode().equals(entity.getIsAllocatedStock())) {
            stockParams.setBusiType(ProductStockBusiTypeEnum.PSBT_Out_Freeze_Sub.getCode());
            productStoctRemoteService.opMultipleSkuStock(stockParams);
        }

        entity.setStatus(OrderStateEnum.OSE_Receiving.getCode());
        entity.setShippingDate(LocalDateTime.now());
        entity.setHandleDate(LocalDateTime.now());
        entity.setHandleUserId(userInfo.getId());
        entity.addEditParam(userInfo);
        orderInfoService.updateById(entity);

        orderItemService.updateBatchById(orderItemUpdateList);
        //MQ
        shopOrderProducer.onOrderChange(entity, orderItemList);
    }

    /**
     * 发货(核销)
     */
    @Transactional
    @Override
    public void checkTicket(OrderTicketCodeCheckParam params, LoginSimpleUserInfo userInfo) {
        OrderInfo entity = orderInfoService.getById(params.getOrderSn());
        if (entity == null) {
            throw new BusinessException(MallErrorEnum.Order_Null);
        }
        if (!OrderStateEnum.OSE_Send.getCode().equals(entity.getStatus())) {
            throw new BusinessException(MallErrorEnum.Order_Op_State);
        }

        if (ShippingMethodEnum.Self_Mention.getCode().equals(entity.getShippingMethod())
                || ShippingMethodEnum.Shop_Consume.getCode().equals(entity.getShippingMethod())) {
        } else {
            throw new BusinessException(MallErrorEnum.Order_Op_ShippingMethod_Not);
        }

        if (!userInfo.getCompanyNo().equals(entity.getMainCompanyNo())) {
            throw new BusinessException(MallErrorEnum.Order_Op_Business_Error);
        }


        OrderItemTicketCode ticketCode = orderItemTicketCodeService.getOne(
                new QueryWrapper<OrderItemTicketCode>()
                        .eq("order_sn", params.getOrderSn())
                        .eq("ticket_code", params.getTicketCode())
        );
        if (ticketCode == null) {
            throw new BusinessException(BaseReturnEnum.DATA_NOT_EXISTS);
        }

        if (!OrderTicketStateEnum.Not_Use.getCode().equals(ticketCode.getState())) {
            throw new BusinessException("已使用");
        }

        ticketCode.setState(OrderTicketStateEnum.Yes_Use.getCode());
        ticketCode.setUseDt(LocalDateTime.now());
        ticketCode.setUseUserId(userInfo.getId());
        ticketCode.addEditParam(userInfo);
        orderItemTicketCodeService.updateById(ticketCode);

        int notUseNum = orderItemTicketCodeService.count(new QueryWrapper<OrderItemTicketCode>()
                .eq("order_sn", params.getOrderSn())
                .eq("state", OrderTicketStateEnum.Not_Use.getCode())
        );

        if (notUseNum <= 0) {
            entity.setStatus(OrderStateEnum.OSE_Complete.getCode());
            entity.setShippingDate(LocalDateTime.now());
            entity.setCompleteDate(LocalDateTime.now());
            entity.setHandleDate(LocalDateTime.now());
            entity.setHandleUserId(userInfo.getId());
            entity.addEditParam(userInfo);
            orderInfoService.updateById(entity);
        }


    }

    /**
     * 兑换积分
     */
    @Transactional
    @Override
    public void exchangePoint(String sn, LoginSimpleUserInfo userInfo) {
        OrderInfo entity = orderInfoService.getById(sn);
        if (entity == null) {
            throw new BusinessException(MallErrorEnum.Order_Null);
        }
        if (userInfo.getId().intValue() != entity.getUserId().intValue()) {
            throw new BusinessException(MallErrorEnum.Order_User_Error);
        }
        if (StringUtils.isEmpty(entity.getIsExchangePoint())
                || YNEnum.YES.getCode().equals(entity.getIsExchangePoint())) {
            throw new BusinessException(MallErrorEnum.Order_ExchangePoint_Already);
        }
        if (entity.getExchangePoint() == null || entity.getExchangePoint() <= 0) {
            throw new BusinessException(MallErrorEnum.Order_ExchangePoint_Zero);
        }

        if (OrderStateEnum.OSE_Send.getCode().equals(entity.getStatus())
                || OrderStateEnum.OSE_Send_Part.getCode().equals(entity.getStatus())
                || OrderStateEnum.OSE_Receiving.getCode().equals(entity.getStatus())
                || OrderStateEnum.OSE_Complete.getCode().equals(entity.getStatus())) {
        } else {
            throw new BusinessException(MallErrorEnum.Order_Op_State);
        }

        entity.setIsExchangePoint(YNEnum.YES.getCode());
        entity.setHandleDate(LocalDateTime.now());
        entity.setHandleUserId(userInfo.getId());
        entity.addEditParam(userInfo);
        orderInfoService.updateById(entity);


        AcctOpRequest pointParam = new AcctOpRequest();
        pointParam.setUserId(entity.getUserId());
        pointParam.setType(AcctTypeEnum.Point_Acct.getCode());
        pointParam.setIsAcctDetail(YNEnum.YES.getCode());
        pointParam.setOpType(AcctOpTypeEnum.Add_Acct.getCode());
        pointParam.setRelObjType(IRelBusiType.Order_ObjType);
        pointParam.setRelObjNo(entity.getSn());
        pointParam.setFundOp(new BigDecimal(entity.getExchangePoint()));
        pointParam.setFundTax(BigDecimal.ZERO);
        pointParam.setRelBizName("订单兑换积分");
        pointParam.setRelDate(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        pointParam.setBusiType("新增积分");
        pointParam.setMemo("订单兑换积分");
        pointParam.setOpIp(userInfo.getIp());
        pointParam.setOpUserId(userInfo.getId());
        accountRemoteService.opAcct(pointParam);

    }

    @Override
    public void removeByUser(String sn, LoginSimpleUserInfo userInfo) {
        OrderInfo entity = orderInfoService.getById(sn);
        if (entity == null) {
            throw new BusinessException(MallErrorEnum.Order_Null);
        }
        if (userInfo.getId().intValue() != entity.getUserId().intValue()) {
            throw new BusinessException(MallErrorEnum.Order_User_Error);
        }
        if (!OrderStateEnum.OSE_Complete.getCode().equals(entity.getStatus())) {
            throw new BusinessException(MallErrorEnum.Order_Complete_Not);
        }
        entity.setUserDelState(YNEnum.NO.getCode());
        entity.addEditParam(userInfo);
        orderInfoService.updateById(entity);
    }

}
